package cn.yemuysy.code.lingting.model;

import java.util.ArrayList;
import java.util.List;

/**
 * 拼音图数据结构
 * 用于表示文本的所有可能拼音组合，支持多音字处理
 */
public class PinyinGraph {
    
    /**
     * 拼音图节点
     */
    public static class PinyinNode {
        /**
         * 当前位置的所有可能拼音
         */
        private List<String> pinyins;
        
        /**
         * 对应的原始字符
         */
        private char originalChar;
        
        /**
         * 在原文中的位置
         */
        private int position;
        
        public PinyinNode(char originalChar, int position) {
            this.originalChar = originalChar;
            this.position = position;
            this.pinyins = new ArrayList<>();
        }
        
        public void addPinyin(String pinyin) {
            this.pinyins.add(pinyin);
        }
        
        public List<String> getPinyins() {
            return pinyins;
        }
        
        public char getOriginalChar() {
            return originalChar;
        }
        
        public int getPosition() {
            return position;
        }
        
        public int getPinyinCount() {
            return pinyins.size();
        }
        
        @Override
        public String toString() {
            return "PinyinNode{" +
                    "originalChar=" + originalChar +
                    ", position=" + position +
                    ", pinyins=" + pinyins +
                    '}';
        }
    }
    
    /**
     * 拼音图路径 - 表示一种可能的拼音组合
     */
    public static class PinyinPath {
        /**
         * 路径中的拼音序列
         */
        private List<String> pinyinSequence;
        
        /**
         * 对应的字符位置序列
         */
        private List<Integer> positionSequence;
        
        public PinyinPath() {
            this.pinyinSequence = new ArrayList<>();
            this.positionSequence = new ArrayList<>();
        }
        
        public void addPinyin(String pinyin, int position) {
            this.pinyinSequence.add(pinyin);
            this.positionSequence.add(position);
        }
        
        public List<String> getPinyinSequence() {
            return pinyinSequence;
        }
        
        public List<Integer> getPositionSequence() {
            return positionSequence;
        }
        
        public int getLength() {
            return pinyinSequence.size();
        }
        
        public String getPinyinAt(int index) {
            return pinyinSequence.get(index);
        }
        
        public int getPositionAt(int index) {
            return positionSequence.get(index);
        }
        
        /**
         * 获取拼音序列的字符串表示（空格分隔）
         */
        public String getPinyinString() {
            return String.join(" ", pinyinSequence);
        }
        
        @Override
        public String toString() {
            return "PinyinPath{" +
                    "pinyinSequence=" + pinyinSequence +
                    ", positionSequence=" + positionSequence +
                    '}';
        }
    }
    
    /**
     * 图中的所有节点
     */
    private List<PinyinNode> nodes;
    
    /**
     * 原始文本
     */
    private String originalText;
    
    public PinyinGraph(String originalText) {
        this.originalText = originalText;
        this.nodes = new ArrayList<>();
    }
    
    /**
     * 添加节点到图中
     */
    public void addNode(PinyinNode node) {
        nodes.add(node);
    }
    
    /**
     * 获取指定位置的节点
     */
    public PinyinNode getNode(int position) {
        if (position >= 0 && position < nodes.size()) {
            return nodes.get(position);
        }
        return null;
    }
    
    /**
     * 获取图的大小（节点数量）
     */
    public int size() {
        return nodes.size();
    }
    
    /**
     * 计算所有可能的拼音路径数量
     */
    public long getTotalPathCount() {
        long total = 1;
        for (PinyinNode node : nodes) {
            total *= node.getPinyinCount();
            // 避免数值溢出
            if (total > Integer.MAX_VALUE) {
                return Integer.MAX_VALUE;
            }
        }
        return total;
    }
    
    /**
     * 生成所有可能的拼音路径
     * 注意：当路径数量过多时，此方法可能消耗大量内存
     */
    public List<PinyinPath> getAllPaths() {
        List<PinyinPath> allPaths = new ArrayList<>();
        if (nodes.isEmpty()) {
            return allPaths;
        }
        
        generatePaths(0, new PinyinPath(), allPaths);
        return allPaths;
    }
    
    /**
     * 递归生成所有拼音路径
     */
    private void generatePaths(int nodeIndex, PinyinPath currentPath, List<PinyinPath> allPaths) {
        if (nodeIndex >= nodes.size()) {
            // 到达末尾，添加当前路径的副本
            PinyinPath pathCopy = new PinyinPath();
            for (int i = 0; i < currentPath.getLength(); i++) {
                pathCopy.addPinyin(currentPath.getPinyinAt(i), currentPath.getPositionAt(i));
            }
            allPaths.add(pathCopy);
            return;
        }
        
        PinyinNode currentNode = nodes.get(nodeIndex);
        for (String pinyin : currentNode.getPinyins()) {
            currentPath.addPinyin(pinyin, currentNode.getPosition());
            generatePaths(nodeIndex + 1, currentPath, allPaths);
            // 回溯
            currentPath.getPinyinSequence().remove(currentPath.getLength() - 1);
            currentPath.getPositionSequence().remove(currentPath.getLength());
        }
    }
    
    /**
     * 检查是否包含多音字
     */
    public boolean hasMultiPronunciation() {
        for (PinyinNode node : nodes) {
            if (node.getPinyinCount() > 1) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 获取多音字节点的数量
     */
    public int getMultiPronunciationCount() {
        int count = 0;
        for (PinyinNode node : nodes) {
            if (node.getPinyinCount() > 1) {
                count++;
            }
        }
        return count;
    }
    
    public List<PinyinNode> getNodes() {
        return nodes;
    }
    
    public String getOriginalText() {
        return originalText;
    }
    
    @Override
    public String toString() {
        return "PinyinGraph{" +
                "originalText='" + originalText + '\'' +
                ", nodeCount=" + nodes.size() +
                ", totalPaths=" + getTotalPathCount() +
                ", hasMultiPronunciation=" + hasMultiPronunciation() +
                '}';
    }
} 